package fhq.hcmute.edu.vn.activities;

import java.util.ArrayList;
import java.util.List;

import android.app.Activity;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.ScanResult;
import android.net.wifi.WifiConfiguration;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.Button;
import android.widget.CompoundButton;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import android.widget.ToggleButton;
import fhq.hcmute.edu.vn.adapter.WiFiAdapter;
import fhq.hcmute.edu.vn.adapter.WiFiItem;
import fhq.hcmute.edu.vn.languages.Language;
import fhq.hcmute.edu.vn.util.BundleUtil;

public class WifiManagerActivity extends Activity {

	private static final int WIFI_PRIORITY = 40;
	private static final int POOR = 3;
	private static final int FAIR = 2;
	private static final int GOOD = 1;
	private static final int EXCELLENT = 0;
	private static final int TIME_OUT = 30000;
	private static final int WIFI_AUTHENTICATION_ERROR = 1;
	private static final int WIFI_CONNECTED = 0;
	private ToggleButton tgbWifiState;
	private Button btnScan;
	private WifiManager mainWifi;
	private ListView wifiListView;
	private List<WiFiItem> listWiFi = new ArrayList<WiFiItem>();
	private List<ScanResult> wifiList;
	private WiFiAdapter adapter;
	private TextView txtWarning;
	public static final int WIFI_CONNECTOR_REQUEST_CODE = 1;
	private WiFiItem currentWiFiAP;
	private int position = -1;
	private boolean isWiFiConnected = false;
	private ProgressDialog progressDialog;

	private BroadcastReceiver receiverWifi = new BroadcastReceiver() {

		@Override
		public void onReceive(Context c, Intent intent) {
			wifiList = mainWifi.getScanResults();
			listWiFi.clear();
			String wifiConnected = currentWiFiConnected();
			for (int i = 0; i < wifiList.size(); i++) {
				ScanResult result = wifiList.get(i);
				String name = result.SSID;
				String security;
				if (name.equals(wifiConnected)) {
					security = getResources().getString(
							R.string.Label_WiFi_Connected);
				} else {
					security = result.capabilities;
				}
				int imgID = result.level;
				WiFiItem item = new WiFiItem(name, imgID, security);
				listWiFi.add(item);
			}
			txtWarning.setVisibility(View.GONE);
			wifiListView.setVisibility(View.VISIBLE);
			adapter.setWiFiItems(listWiFi);
			adapter.notifyDataSetChanged();
		}
	};

	private String currentWiFiConnected() {
		WifiManager myWifiManager =
				(WifiManager) getSystemService(Context.WIFI_SERVICE);
		WifiInfo myWifiInfo = myWifiManager.getConnectionInfo();
		if (myWifiInfo != null) {
			return myWifiInfo.getSSID();
		}
		return "";
	}

	@Override
	public final void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		Language.updateLanguageSystem(getBaseContext());
		setContentView(R.layout.activity_wifi_manager);
		txtWarning = (TextView) findViewById(R.id.txtWarning);
		tgbWifiState = (ToggleButton) findViewById(R.id.tgbWifiState);
		tgbWifiState.setOnCheckedChangeListener(onWifiStateChange);
		btnScan = (Button) findViewById(R.id.btnScan);
		btnScan.setOnClickListener(onOKClickListener);
		wifiListView = (ListView) findViewById(R.id.lvWiFi);
		wifiListView.setOnItemClickListener(onListItemClickListener);
		mainWifi = (WifiManager) getSystemService(Context.WIFI_SERVICE);
		currentWiFiAP = new WiFiItem("", 0, "");
		Bundle bundle = getIntent().getExtras();
		if (bundle != null) {
			tgbWifiState.setChecked(bundle
					.getBoolean(MainActivity.WIFI_CONNECTED));
		}
	}

	public final boolean isWiFiConnected() {
		return isWiFiConnected;
	}

	public final void setWiFiConnected(boolean isWiFiConnected) {
		this.isWiFiConnected = isWiFiConnected;
	}

	@Override
	protected final void onActivityResult(int requestCode,
			int resultCode, Intent data) {
		if (requestCode == WIFI_CONNECTOR_REQUEST_CODE) {
			if (resultCode == WiFiConnectorActivity.WIFI_CONNECTOR_RESULT_CODE_OK) {
				Bundle bundle = data.getExtras();
				String password =
						bundle.getString(BundleUtil.WIFI_PASSWORD);
				wifiConnectorHelper(currentWiFiAP.getName(), password,
						currentWiFiAP.getSecurityType());

			} else if (resultCode == WiFiConnectorActivity.WIFI_CONNECTOR_RESULT_CODE_CANCEL) {
				Toast.makeText(getApplicationContext(), "cancel",
						Toast.LENGTH_SHORT).show();
			}
		}
		super.onActivityResult(requestCode, resultCode, data);
	}

	private void wifiConnectorHelper(String accessPoint, String password,
			int securityType) {
		WifiManager wifiManager =
				(WifiManager) getSystemService(Context.WIFI_SERVICE);
		// setup a wifi configuration
		WifiConfiguration wc = new WifiConfiguration();
		if (securityType == WifiConfiguration.KeyMgmt.WPA_PSK) {
			connectWiFiWAPHelper(accessPoint, password, wifiManager, wc);
		} else if (securityType == WifiConfiguration.KeyMgmt.IEEE8021X) {
			connectWiFiWEPHelper(accessPoint, password,
					wifiManager, wc);
		} //
		new WiFiConnectingAsyn().execute(System.currentTimeMillis());
	}

	/**
	 * @param accessPoint
	 * @param password
	 * @param securityType
	 * @param wifiManager
	 * @param wc
	 */
	private void connectWiFiWAPHelper(String accessPoint, String password,
			WifiManager wifiManager, WifiConfiguration wc) {
		wc.SSID = String.format("\"%s\"", accessPoint);
		wc.preSharedKey = String.format("\"%s\"", password);
		wc.status = WifiConfiguration.Status.ENABLED;
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
		wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.WPA_PSK);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
		wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
		// connect to and enable the connection
		int netId = wifiManager.addNetwork(wc);
		wifiManager.disconnect();
		wifiManager.enableNetwork(netId, true);
		wifiManager.setWifiEnabled(true);
		wifiManager.reconnect();
	}

	/**
	 * @param accessPoint
	 * @param password
	 * @param securityType
	 * @param wifiManager
	 * @param wc
	 */
	private void connectOpenWiFiHelper(String accessPoint) {
		WifiManager wifiManager =
				(WifiManager) getSystemService(Context.WIFI_SERVICE);
		// setup a wifi configuration
		WifiConfiguration wc = new WifiConfiguration();
		wc.SSID = String.format("\"%s\"", accessPoint);
		wc.status = WifiConfiguration.Status.ENABLED;
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.TKIP);
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.CCMP);
		wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
		wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
		// connect to and enable the connection
		int netId = wifiManager.addNetwork(wc);
		wifiManager.disconnect();
		wifiManager.enableNetwork(netId, true);
		wifiManager.setWifiEnabled(true);
		wifiManager.reconnect();
	}

	/**
	 * @param accessPoint
	 * @param password
	 * @param securityType
	 * @param wifiManager
	 * @param wc
	 */
	private void connectWiFiWEPHelper(String accessPoint, String password,
			WifiManager wifiManager, WifiConfiguration wc) {
		wc.SSID = String.format("\"%s\"", accessPoint);
		wc.wepKeys[0] = String.format("\"%s\"", password);
		wc.wepTxKeyIndex = 0;
		wc.status = WifiConfiguration.Status.DISABLED;
		wc.priority = WIFI_PRIORITY;
		wc.allowedKeyManagement.set(WifiConfiguration.KeyMgmt.NONE);
		wc.allowedProtocols.set(WifiConfiguration.Protocol.RSN);
		wc.allowedProtocols.set(WifiConfiguration.Protocol.WPA);
		wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.OPEN);
		wc.allowedAuthAlgorithms.set(WifiConfiguration.AuthAlgorithm.SHARED);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.CCMP);
		wc.allowedPairwiseCiphers.set(WifiConfiguration.PairwiseCipher.TKIP);
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP40);
		wc.allowedGroupCiphers.set(WifiConfiguration.GroupCipher.WEP104);
		WifiManager wifiManag =
				(WifiManager) this.getSystemService(WIFI_SERVICE);
		wifiManag.setWifiEnabled(true);
		int netId = wifiManager.addNetwork(wc);
		wifiManager.disconnect();
		wifiManager.enableNetwork(netId, true);
		wifiManager.setWifiEnabled(true);
		wifiManager.reconnect();

	}

	private String getSignalName(int signal) {
		String[] temp = getResources().getStringArray(R.array.SignalStrength);
		if (signal == R.drawable.wifi_excellent) {
			return temp[EXCELLENT]; // Excellent
		} else if (signal == R.drawable.wifi_good) {
			return temp[GOOD]; // Good
		} else if (signal == R.drawable.wifi_fair) {
			return temp[FAIR]; // Fair
		}
		return temp[POOR]; // Poor
	}

	private void showPasswordInput(int position) {
		this.position = position;
		Intent intent = new Intent(getApplicationContext(),
				WiFiConnectorActivity.class);
		Bundle bundle = new Bundle();
		bundle.putString(BundleUtil.WIFI_NAME,
				currentWiFiAP.getName());
		bundle.putString(BundleUtil.WIFI_SECURITY_TYPE,
				currentWiFiAP.getCapabilities());
		bundle.putString(BundleUtil.WIFI_SIGNAL_STRENGTH,
				getSignalName(currentWiFiAP.getSignal()));
		intent.putExtra(WifiManagerActivity.class.getName(), bundle);
		startActivityForResult(intent,
				WIFI_CONNECTOR_REQUEST_CODE);
	}

	private OnItemClickListener onListItemClickListener =
			new OnItemClickListener() {

				@Override
				public void onItemClick(AdapterView<?> arg0, View view,
						int position, long id) {
					currentWiFiAP = listWiFi.get(position);
					if (currentWiFiAP.getSecurityType() != WifiConfiguration.KeyMgmt.NONE) {
						showPasswordInput(position);
					} else {
						connectOpenWiFiHelper(currentWiFiAP.getName());
					}
				}
			};

	@Override
	protected final void onResume() {
		registerReceiver(receiverWifi, new IntentFilter(
				WifiManager.SCAN_RESULTS_AVAILABLE_ACTION));
		super.onResume();
	}

	private void updateWifi() {
		adapter = new WiFiAdapter(WifiManagerActivity.this,
				listWiFi);
		wifiListView.setAdapter(adapter);
	}

	private OnCheckedChangeListener onWifiStateChange =
			new CompoundButton.OnCheckedChangeListener() {

				@Override
				public void onCheckedChanged(CompoundButton buttonView,
						boolean isChecked) {
					WifiManager wifiManager =
							(WifiManager) getBaseContext().getSystemService(
									Context.WIFI_SERVICE);
					wifiManager.setWifiEnabled(isChecked);
					if (isChecked) {
						txtWarning.setText(getResources().getString(
								R.string.Label_Wifi_Scanning));
						mainWifi.startScan();
						updateWifi();
					} else {
						txtWarning.setText(getResources().getString(
								R.string.Label_WiFi_Warning));
						wifiList.clear();
						adapter.setWiFiItems(listWiFi);
						adapter.clear();
						adapter.notifyDataSetChanged();
						wifiListView.setVisibility(View.GONE);
						txtWarning.setVisibility(View.VISIBLE);
					}
				}
			};
	private OnClickListener onOKClickListener = new View.OnClickListener() {

		@Override
		public void onClick(View v) {
			listWiFi.clear();
			mainWifi.startScan();
		}
	};

	@Override
	protected final void onDestroy() {

		super.onDestroy();
	}

	@Override
	protected final void onPause() {
		unregisterReceiver(receiverWifi);
		super.onPause();
	}

	private Handler handler = new Handler() {

		@Override
		public void handleMessage(Message msg) {
			if (msg.what == WIFI_AUTHENTICATION_ERROR) {
				Toast.makeText(
						getApplicationContext(),
						getResources().getString(
								R.string.Label_WiFi_Authentication_Error),
						Toast.LENGTH_SHORT).show();
				showPasswordInput(position);
			} else if (msg.what == WIFI_CONNECTED) {
				adapter.getItem(position).setConnected(true);
				finish();
			}
			super.handleMessage(msg);
		}

	};

	private class WiFiConnectingAsyn extends AsyncTask<Long, Integer, Void> {

		@Override
		protected void onPostExecute(Void result) {
			progressDialog.dismiss();
			cancel(true);
			super.onPostExecute(result);
		}

		@Override
		protected void onPreExecute() {
			progressDialog =
					new ProgressDialog(WifiManagerActivity.this);
			progressDialog.setCanceledOnTouchOutside(false);
			progressDialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
			progressDialog.setMessage(getResources()
					.getString(R.string.Label_WiFi_Authenticating));
			progressDialog.show();
			super.onPreExecute();
		}

		@Override
		protected Void doInBackground(Long... params) {
			long timeStart = params[0];
			while (true) {
				ConnectivityManager myConnManager =
						(ConnectivityManager) getSystemService(CONNECTIVITY_SERVICE);
				NetworkInfo myNetworkInfo =
						myConnManager
								.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
				if (myNetworkInfo.isConnected()) {
					handler.sendEmptyMessage(WIFI_CONNECTED);
					break;
				} else {
					long timeConnecting = System.currentTimeMillis();
					if ((timeConnecting - timeStart) > TIME_OUT) {
						handler.sendEmptyMessage(WIFI_AUTHENTICATION_ERROR);
						break;
					}
				}
				if (isCancelled()) {
					break;
				}
			}
			return null;
		}

	}
}
